/*!
 Temelia - Performance test case implementation for Temelia
 data structures library.

 Copyright (C) 2009 Ceata (http://cod.ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "include/testutil.hpp"

// Working on LINUX operating system
#define LINUX
//#define WINDOWS

#ifdef DEBUG
#include <cstdio>
#include <cstdlib>
#endif

const std::string BASE_DIR = "images/";

TestCase::TestCase(const char *libraryName, const char *functionName)
{
	results = new std::map<int, double>();
	this->libraryName = new std::string(libraryName);
	this->functionName = new std::string(functionName);
	this->key = NULL;
	this->value = NULL;
}

TestCase::~TestCase()
{
	delete results;
	delete libraryName;
	delete functionName;

	if (key)
		delete key;
	if (value)
		delete value;
	key = NULL;
	value = NULL;
}

void TestCase::addTest(int size, double time)
{
	results->insert(std::make_pair(size, time));
}

TestUnit::TestUnit(const char *testName)
{
	this->testName = new std::string(testName);
	tests = new std::list<TestCase *>();
}

TestUnit::~TestUnit()
{
	delete this->testName;

	for (std::list<TestCase *>::iterator it = tests->begin(); it
			!= tests->end(); it++)
		delete *it;

	delete tests;
}

void TestUnit::addTestUnit(TestCase *testUnit)
{
	tests->push_back(testUnit);
}

#ifdef DEBUG

void TestUnit::debug()
{
	/*
	 * Example of how you should iterate over this object.
	 */
	printf("<data_structure name=\"%s\">\n", testName->c_str());
	for (std::list<TestCase *>::iterator it = tests->begin(); it
			!= tests->end(); it++)
	{
		TestCase *test = *it;
		printf("  <test_case function=\"%s\" library=\"%s\">\n",
				test->functionName->c_str(), test->libraryName->c_str());
		std::map<int, double> *results = test->results;

		for (std::map<int, double>::iterator iter = results->begin(); iter
				!= results->end(); iter++)
			printf("    <test_unit input=\"%d\" time=\"%lf\">\n", iter->first,
					iter->second);
		printf("  </test_case>\n");
	}
	printf("</data_structure>");
}

#endif

void TestUnit::write(std::ofstream *fout)
{
	(*fout) << "<data_structure name=\"" << *testName << "\">" << std::endl;
	for (std::list<TestCase *>::iterator it = tests->begin(); it
			!= tests->end(); it++)
	{
		TestCase *test = *it;

		(*fout) << "  <test_case function=\"" << *test->functionName
				<< "\" library=\"" << *test->libraryName;

		if (test->key && test->value)
			(*fout) << " " << *test->key << "=\"" << *test->value << "\"";

		(*fout) << "\">" << std::endl;
		std::map<int, double> * results = test->results;

		for (std::map<int, double>::iterator iter = results->begin(); iter
				!= results->end(); iter++)
			(*fout) << "    <test_unit input=\"" << iter->first << "\" time=\""
					<< iter->second << "\">" << std::endl;
		(*fout) << "  </test_case>" << std::endl;
	}
	(*fout) << "</data_structure>" << std::endl;
	fout->flush();
}

void TestCase::setComment(const char *key, const char *value)
{
	this->key = new std::string(key);
	this->value = new std::string(value);
}

#ifdef DEBUG
void test()
{

	TestUnit test("data_structure");
	TestCase *t = new TestCase("temelia", "map");
	t->addTest(1, 100);
	t->addTest(10, 1000);
	t->addTest(100, 10000);
	t->addTest(1000, 100000);
	test.addTestUnit(t);

	t = new TestCase("stl", "fflush");
	t->addTest(1, 200);
	t->addTest(2, 300);
	test.addTestUnit(t);
	test.debug();
}
#endif

#ifdef CLUSTER_RUNNING
#define CONST const
#else
#define CONST
#endif

CONST int test_size[] =
{ 5, 1000, 2000, 5000, 10000, 20000, 30000, 40000, 70000, 100000, 200000,
		400000, 600000, 800000, 1000000 };
CONST int ntests = 1;

int *default_collection[MAX_TEST_SIZE] =
{ 0, };
clock_t start, stop;

double execute(void(*function)(int), int size)
{
	start = clock();
	function(size);
	stop = clock();
	return (double) (stop - start) / CLOCKS_PER_SEC;
}
